﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using WordStat.ArticlesService;
using WordStat.Tasks;

namespace WordStat
{
    /// <summary>
    /// Interaction logic for TreeGridControl.xaml
    /// </summary>
    public partial class TreeGridControl : UserControl
    {
        public TreeGridControl()
        {
            InitializeComponent();

            var app = Application.Current as App;

            if (app != null)
            {
                _pluginSrv = app.PluginSrv;

                foreach (var iter in _pluginSrv.PluginItems)
                {
                    var menu = new MenuItem { Header = iter.Name };
                    menu.Click += providerClick;
                    _plugins.Items.Add(menu);
                }
            }

            var settings = new WordStatSettings();
            settings.LoadFromAppConfig();
            _rowsOnGrid = settings.RowNumber;
        }

        private int _rowsOnGrid = 20;

        private PluginService.PluginService _pluginSrv;

        private void providerClick(object sender, RoutedEventArgs e)
        {
            var menuItem = (MenuItem)sender;

            var header = menuItem.Header.ToString();

            if (string.IsNullOrWhiteSpace(header))
                return;

            var plugin = _pluginSrv.GetPlugin(header);

            if (plugin == null)
                return;

            var taskService = new TaskService();
            taskService.ShowWizard(plugin);
        }

        private FileContainer _fileContainer;

        private void TasksClick(object sender, RoutedEventArgs e)
        {
            var tSrv = new TaskService();
            tSrv.ShowTasks();
        }

        private ArticleService _dataSrv;

        public void SetArticleService(ArticleService dataSrv)
        {
            _dataSrv = dataSrv;

            UpdateSources();
        }

        public void UpdateSources()
        {
            _treeView.Items.Clear();
            var data = _dataSrv.GetItem();

            var treeStyle = (Style)FindResource("TreeViewItem");
            data.Style = treeStyle;

            foreach (var item in data.Items)
                ((TreeViewItem)item).Style = treeStyle;

            _treeView.Items.Add(data);
            data.IsSelected = true;
        }

        private void _treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            var selectedItem = _treeView.SelectedItem as TreeViewItem;

            if (selectedItem == null)
                return;

            _selectedItem = selectedItem;

            UpdateDataGrid();
        }

        private void _dataGrid_RowDetailsVisibilityChanged(object sender, DataGridRowDetailsEventArgs e)
        {
            var dg = e.DetailsElement as DataGrid;

            if (dg == null)
                return;

            var wordRecord = e.Row.Item as WordRecord;

            if (wordRecord == null)
                return;

            var wordData = _dataSrv.GetArticles(wordRecord.Text, _currentSource);

            dg.ItemsSource = wordData.Select(w => new ArticleRecord { Title = w.Key.Title, Url = w.Key.Url, WordCount = w.Value, WordText = wordRecord.Text, ArticleText = w.Key.Text }).ToList();
        }

        private void _nestedDataGrid_RowDetailsVisibilityChanged(object sender, DataGridRowDetailsEventArgs e)
        {
            var dockPanel = e.DetailsElement as DockPanel;

            if (dockPanel == null)
                return;

            var articleRecord = e.Row.Item as ArticleRecord;

            if (articleRecord == null)
                return;

            dockPanel.Children.Clear();

            var texts = GetParts(articleRecord.ArticleText, articleRecord.WordText, articleRecord.WordCount);

            foreach (var text in texts)
            {
                var myFlowDoc = new FlowDocument();

                // Add paragraphs to the FlowDocument.
                myFlowDoc.Blocks.Add(new Paragraph(new Run(text.Text)));
                var myRichTextBox = new RichTextBox { Document = myFlowDoc, Width = 350 };

                var startPos = myRichTextBox.Document.ContentStart.GetPositionAtOffset(text.Start);
                var endPos = myRichTextBox.Document.ContentStart.GetPositionAtOffset(text.Start + text.Length);

                if (startPos != null && endPos != null)
                {
                    var textRange = new TextRange(startPos, endPos);

                    textRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
                }

                DockPanel.SetDock(myRichTextBox, Dock.Top);

                dockPanel.Children.Add(myRichTextBox);
            }
        }

        private List<TextRec> GetParts(string articleText, string word, int wordCount)
        {
            var res = new List<TextRec>();
            int i = 0;

            int startIndex = 0;

            do
            {
                var index = articleText.IndexOf(word, startIndex, StringComparison.InvariantCultureIgnoreCase);

                if (index == -1)
                    break;

                var start = index - _charCount;

                if (start < 0)
                    start = 0;

                var end = index + _charCount;

                if (end >= articleText.Length)
                    end = articleText.Length - 1;

                var length = end - start;

                if (length < 0)
                    break;

                var article = new TextRec { Text = articleText.Substring(start, length) };

                var startWordIndex = article.Text.IndexOf(word, StringComparison.InvariantCultureIgnoreCase);

                if (startWordIndex == -1)
                    break;

                res.Add(new TextRec { Text = articleText.Substring(start, length), Start = startWordIndex + 2, Length = word.Length });

                startIndex = index + 1;

                if (startIndex >= articleText.Length)
                    break;

            } while (i < wordCount);

            return res;
        }

        private void UpdateDataGrid()
        {
            var curCursor = Cursor;
            try
            {
                Cursor = Cursors.Wait;

                var data = _dataSrv.GetDataFrom(_selectedItem, _pageNumber, _rowsOnGrid, _sortByName);
                if (data == null || data.Count == 0)
                {
                    _dataGrid.DataContext = null;
                    return;
                }

                var list = data.Select(iter => new WordRecord { Text = iter.Key, WordCount = iter.Value }).ToList();

                _dataGrid.DataContext = list;
            }
            finally
            {
                Cursor = curCursor;
            }
        }

        private string _currentSource = string.Empty;
        private TreeViewItem _selectedItem;

        private void OnHyperLink(object sender, RoutedEventArgs e)
        {
            var destination = ((Hyperlink)e.OriginalSource).NavigateUri;
            try
            {
                Process.Start(destination.ToString());
            }
            catch
            {
                //Nothing
            }
        }

        private void _prevBtn_Click(object sender, RoutedEventArgs e)
        {
            _isTextChanging = true;

            if (_pageNumber != 0)
                _pageNumber--;

            _pageNumberTextBlock.Text = _pageNumber.ToString();

            UpdateDataGrid();

            _isTextChanging = false;
        }

        private void _prev10Btn_Click(object sender, RoutedEventArgs e)
        {
            _isTextChanging = true;

            _pageNumber -= 10;

            if (_pageNumber < 0)
                _pageNumber = 0;

            _pageNumberTextBlock.Text = _pageNumber.ToString();

            UpdateDataGrid();

            _isTextChanging = false;
        }

        private void _nextBtn_Click(object sender, RoutedEventArgs e)
        {
            _isTextChanging = true;

            _pageNumber += 1;

            _pageNumberTextBlock.Text = _pageNumber.ToString();

            UpdateDataGrid();

            _isTextChanging = false;
        }

        private void _next10Btn_Click(object sender, RoutedEventArgs e)
        {
            _isTextChanging = true;

            _pageNumber += 10;

            _pageNumberTextBlock.Text = _pageNumber.ToString();

            UpdateDataGrid();

            _isTextChanging = false;
        }

        private int _pageNumber;
        private int _charCount = 100;
        private bool _isTextChanging;

        private void _pageNumberTextBlock_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (_isTextChanging)
                return;

            int pageNumber;

            if (!int.TryParse(_pageNumberTextBlock.Text, out pageNumber))
                return;

            _pageNumber = pageNumber;

            UpdateDataGrid();
        }

        private void _sortBtn_Click(object sender, RoutedEventArgs e)
        {
            var btn = (Button)sender;

            _sortByName = !_sortByName;

            btn.Content = _sortByName ? "Sort by count" : "Sort by name";

            _pageNumber = 0;

            UpdateDataGrid();
        }

        private void SettingsCmd(object sender, RoutedEventArgs e)
        {
            var settings = new WordStatSettings();

            settings.LoadFromAppConfig();

            var settingsWindow = new EditSettingsWindow();
            settingsWindow.SetData(settings);

            settingsWindow.ShowDialog();

            settings.SaveToAppConfig();

            _rowsOnGrid = settings.RowNumber;

            UpdateDataGrid();
        }

        private sealed class TextRec
        {
            public string Text { get; set; }

            public int Start { get; set; }

            public int Length { get; set; }
        }

        private bool _sortByName;

        private void EditArticlesClick(object sender, RoutedEventArgs e)
        {
            var window = new ArticlesEditWindow();

            window.ShowDialog();
            
            UpdateDataGrid();
        }
    }
}
